"""
工具2：候选人检索工具（核心工具）
功能：复用现有RAG系统进行候选人检索
"""
import json
import logging
from typing import Optional, Dict
from langchain.tools import BaseTool

logger = logging.getLogger(__name__)


class CandidateSearchTool(BaseTool):
    """
    候选人检索工具
    
    核心功能：
    - 复用现有RAG混合检索系统（ES + ChromaDB）
    - 支持语义检索 + 结构化过滤
    - 返回排序后的候选人列表
    """
    
    name: str = "candidate_search_tool"
    description: str = """
        在简历数据库中检索匹配的候选人，使用混合检索算法。
        
        ⭐ 核心功能：
        - 语义检索：理解岗位描述的含义
        - 结构化过滤：按城市、学历、经验筛选
        - 智能排序：综合评分排序
        
        📥 输入参数（JSON字符串）：
        {
            "query_text": "查询文本（必填），如：Python工程师，3年经验，熟悉Django",
            "top_k": 10,
            "filters": {
                "city": "杭州",
                "education": "本科",
                "experience": "3-5年"
            }
        }
        
        📤 返回格式（JSON字符串）：
        {
            "success": true,
            "data": [
                {
                    "id": 123,
                    "title": "Python开发工程师",
                    "company": "阿里巴巴",
                    "city": "杭州",
                    "tags": "Python,Django,MySQL",
                    "score": 0.92,
                    "match_reason": "技能匹配度高"
                },
                ...
            ],
            "message": "检索到10个候选人"
        }
        
        ⚠️ 注意：
        - 该工具调用可能需要3-5秒
        - 复用项目中的 hybrid_search_jobs() 函数
        - 返回结果已按匹配度排序
        """
    
    def _run(
        self, 
        query_text: str,
        top_k: int = 10,
        filters: Optional[str] = None
    ) -> str:
        """
        执行候选人检索
        
        Args:
            query_text: 查询文本
            top_k: 返回数量
            filters: 过滤条件（JSON字符串）
        
        Returns:
            JSON字符串格式的检索结果
        """
        try:
            # 1. 参数校验
            if not query_text or not query_text.strip():
                return self._error_response("query_text不能为空")
            
            # 解析filters（如果是字符串）
            filter_dict = {}
            if filters:
                if isinstance(filters, str):
                    try:
                        filter_dict = json.loads(filters)
                    except:
                        logger.warning(f"无法解析filters: {filters}")
                elif isinstance(filters, dict):
                    filter_dict = filters
            
            logger.info(f"开始检索候选人: query={query_text[:50]}, top_k={top_k}")
            
            # 2. 调用现有RAG系统（不修改原代码）
            from rag.job_recommendation.job_recommendation import hybrid_search_jobs
            
            results = hybrid_search_jobs(
                query_text=query_text,
                top_k=top_k,
                weight_es=0.6,
                weight_chroma=0.4
            )
            
            # 3. 格式化结果
            if not results:
                return self._success_response(
                    data=[],
                    message="未找到匹配的候选人，建议调整搜索条件"
                )
            
            candidates = self._format_candidates(results, filter_dict)
            
            # 4. 返回结果
            logger.info(f"检索完成: 找到{len(candidates)}个候选人")
            return self._success_response(
                data=candidates,
                message=f"检索到{len(candidates)}个候选人"
            )
            
        except ImportError as e:
            logger.error(f"RAG模块导入失败: {str(e)}")
            return self._error_response("检索服务暂时不可用，请稍后重试")
        except Exception as e:
            logger.error(f"候选人检索失败: {str(e)}", exc_info=True)
            return self._error_response(f"检索失败: {str(e)}")
    
    def _format_candidates(self, raw_results: list, filters: dict) -> list:
        """
        格式化候选人数据
        
        Args:
            raw_results: RAG系统原始返回
            filters: 过滤条件
        
        Returns:
            格式化后的候选人列表
        """
        candidates = []
        
        for item in raw_results:
            # 应用过滤条件
            if filters:
                # 城市过滤
                if 'city' in filters:
                    if item.get('city', '') != filters['city']:
                        continue
                
                # 学历过滤（简化版）
                if 'education' in filters:
                    if filters['education'] not in item.get('education', ''):
                        continue
            
            # 构造候选人数据
            candidate = {
                "id": item.get("id"),
                "title": item.get("title", ""),
                "company": item.get("company", ""),
                "city": item.get("city", ""),
                "tags": item.get("tags", ""),
                "education": item.get("education", ""),
                "score": round(item.get("_fused_score", 0), 2),
                "es_score": round(item.get("_es_original_score", 0), 2),
                "vec_score": round(item.get("_chroma_original_score", 0), 2),
                "match_reason": self._generate_match_reason(item)
            }
            
            candidates.append(candidate)
        
        return candidates
    
    def _generate_match_reason(self, item: Dict) -> str:
        """
        生成匹配理由（简化版）
        
        完整版可以调用LLM生成个性化理由
        """
        tags = item.get("tags", "")
        score = item.get("_fused_score", 0)
        
        if score >= 0.9:
            reason = f"✅ 完美匹配！技能：{tags}"
        elif score >= 0.8:
            reason = f"✅ 高度匹配，技能：{tags}"
        elif score >= 0.7:
            reason = f"⚠️ 基本匹配，技能：{tags}"
        else:
            reason = f"📊 综合评分：{score:.2f}"
        
        return reason
    
    def _success_response(self, data: list, message: str) -> str:
        """成功响应"""
        return json.dumps({
            "success": True,
            "data": data,
            "message": message
        }, ensure_ascii=False)
    
    def _error_response(self, error: str) -> str:
        """失败响应"""
        return json.dumps({
            "success": False,
            "error": error,
            "message": "操作失败"
        }, ensure_ascii=False)
    
    async def _arun(self, *args, **kwargs):
        """异步执行（暂不实现）"""
        raise NotImplementedError("暂不支持异步调用")


